﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using LoungeRepo.Normalizer;
using LoungeRepo.Normalizer.DataStructures;
using NUnit.Framework;

namespace Test.LoungeRepo.Normalizer
{
    [TestFixture]
    public class testObjectGraphDenormalizer
    {
        [Test]
        public void Denormalize_simple_object()
        {
            NormalizedObject no = new NormalizedObject(typeof (Simple));
            no.AddField("Text", "hello, world!");

            var sut = new ObjectGraphDenormalizer(null);
            object deno = sut.Denormalize(no);

            Assert.IsTrue(deno is Simple);
            Assert.AreEqual("hello, world!", ((Simple) deno).Text);
        }


        [Test]
        public void Denormalize_null_value()
        {
            NormalizedObject no = new NormalizedObject(typeof(Simple));
            no.AddField("Text", null);

            var sut = new ObjectGraphDenormalizer(null);
            object deno = sut.Denormalize(no);

            Assert.IsNull(((Simple)deno).Text);
        }


        [Test]
        public void Denormalize_only_nontransient_fields()
        {
            NormalizedObject no = new NormalizedObject(typeof (Node));
            no.AddField("Text", null);
            no.AddField("Comment", "do not denormalize");
            no.AddField("Child", null);

            var sut = new ObjectGraphDenormalizer(null);
            object deno = sut.Denormalize(no);

            Assert.IsNull(((Node) deno).Comment);
        }


        [Test]
        public void Denormalize_object_graphs()
        {
            NormalizedObject noChild = new NormalizedObject(typeof (Node));
            noChild.AddField("Text", "c");
            noChild.AddField("Comment", null);
            noChild.AddField("Child", null);

            NormalizedObject noParent = new NormalizedObject(typeof (Node));
            noParent.AddField("Text", "p");
            noParent.AddField("Comment", null);
            noParent.AddField("Child", noChild);

            var sut = new ObjectGraphDenormalizer(null);
            var parent = (Node)sut.Denormalize(noParent);

            Assert.AreEqual("c", parent.Child.Text);
        }


        [Test]
        public void Denormalize_cyclic_object_graphs()
        {
            NormalizedObject noParent = new NormalizedObject(typeof(Node));
            NormalizedObjectReference noParentRef = new NormalizedObjectReference(noParent);
            noParent.AddField("Text", "p");
            noParent.AddField("Comment", null);
            noParent.AddField("Child", noParentRef);

            var sut = new ObjectGraphDenormalizer(null);
            var parent = (Node)sut.Denormalize(noParent);

            Assert.AreSame(parent, parent.Child);
        }


        [Test]
        public void Resolve_nested_entity()
        {
            NormalizedEntity ne = new NormalizedEntity("myid", "mypartition", typeof (EntityNode));
            ne.AddField("_id", "myid");
            ne.AddField("_partition", "mypartition");
            ne.AddField("Next", null);

            NormalizedEntityReference neRef = new NormalizedEntityReference(ne);

            NormalizedObject no = new NormalizedObject(typeof (ObjectReferencingEntities));
            no.AddField("E1", neRef);
            no.AddField("E2", null);

            var sut = new ObjectGraphDenormalizer(eid => ne);

            var o = (ObjectReferencingEntities)sut.Denormalize(no);

            Assert.AreEqual("myid", o.E1.Id);
        }


        [Test]
        public void Denormalize_single_dim_array()
        {
            NormalizedObject no = new NormalizedObject(typeof (string[]));
            no.AddField("_arrayRank", 1);
            no.AddField("_dimLength", 2);
            no.AddField("0", "a");
            no.AddField("1", "b");

            var sut = new ObjectGraphDenormalizer(null);
            var array = (string[])sut.DenormalizeArray(no);

            Assert.AreEqual(2, array.Length);
            Assert.AreEqual("b", array[1]);
        }


        [Test]
        public void Denormalize_multi_dim_array()
        {
            NormalizedObject no = new NormalizedObject(typeof(string[,]));
            no.AddField("_arrayRank", 2);
            no.AddField("_dimLength", 2);
            no.AddField("_dimLength", 3);
            no.AddField("0", "1");
            no.AddField("1", "11");
            no.AddField("2", "111");
            no.AddField("3", "2");
            no.AddField("4", "22");
            no.AddField("5", "222");

            var sut = new ObjectGraphDenormalizer(null);
            var array = (string[,])sut.DenormalizeArray(no);

            Assert.AreEqual(6, array.Length);
            Assert.AreEqual("11", array[0,1]);
            Assert.AreEqual("222", array[1, 2]);
        }
    }
}
